package com.example.demoboot.service.impl;

import com.example.demoboot.error.ErrorMessage;
import com.example.demoboot.meiju.StatusEnumList;
import com.example.demoboot.model.SubClassSelectVo;
import com.example.demoboot.model.SubClassVo;
import com.example.demoboot.service.POIService;
import com.example.demoboot.util.*;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

@Service
public class POIServiceImpl implements POIService {

    /**
     * 1.验证版本 2007
     * 2.验证是不是正确的模板-读取里面的内容，poi读取
     * 3.读取其中的数据放到java对象-poi读取内容
     * 4.一系列的验证：
     * 1.不为空字段是否为空
     * 5.长度验证
     * 6.重复验证,要求，要把重复的提示出来
     * 7.数据转换，把汉字转换成数据库的值，状态必须填启用，禁用
     * 8.唯一性验证，编码  名称,是否存在
     * 9.批量入库
     * 10.导入数据量过大怎么办？
     * 怎么解决？
     * 高大上： 把数据切割开，一部分数据扔到一台机器，另一部分扔到另外的机器。-淘汰。
     * 很实用，很简单的方案：控制用户导入的条数，每次只允许导入3000条，超过3000条，让他自己分割数据，分批次导入。
     * 特殊情况：
     *  1.在一个excel表格中有多个单元格有数据，就读取多个单元格，顺序处理即可。
     *  2.一个单元格两组数据，根据列的不同，顺序处理即可。
     *  3.企业要求不限制版本，2003都能用！
     */
    @Override
    public ResultVo importFile(MultipartFile file) throws Exception{
        //判断名称
        //使用poi读取里面的内容
        XSSFWorkbook workbook = new XSSFWorkbook(file.getInputStream());

        //获取单元格中的信息 at0是获取sheet1中的数据。
        XSSFSheet sheet = workbook.getSheetAt(0);
//        XSSFSheet sheet1 = workbook.getSheetAt(1);
        /*chuliSheet0(sheet){

        }
        chuliSheet1(sheet){

        }*/
        ResultVo validata = validata(file,sheet);
        if (!validata.getSuccess()){
            return validata;
        }
        //获取数据
        ResultVo<List<SubClassVo>> data = getData(sheet);
        if (!data.getSuccess()){
            return data;
        }
        //验证条数

        //验证是否为空，长度，数据转换
        ResultVo resultVo = validataRepeatIsNull(data.getData());
        if (!resultVo.getSuccess()){
            return resultVo;
        }
        ResultVo resultVo1 = validataChongFu(data.getData());
        if (!resultVo1.getSuccess()){
            return resultVo1;
        }
//        add();
        return ResultBuildVo.success();
    }

    @Override
    public ResultVo exportFile(SubClassSelectVo subClassSelectVo, HttpServletResponse response) throws Exception{

        //获取数据
        List<SubClassVo> subClassVoList = new ArrayList<>();
        SubClassVo subClassVo = new SubClassVo();
        subClassVo.setName("测试数据");
        subClassVo.setCode("测试编码");
        subClassVoList.add(subClassVo);
        ServletOutputStream out= response.getOutputStream();
        POIClass.toPackageOs(response, "备件小类导出");
        //读取模板数据
        InputStream in = ExportUtil.toPackageIn("export/2007.xlsx");
        //使用poi获取到模板数据，并且把查询到的信息写入到模板中
        //in模板信息   out，响应给浏览器的内容
        writeDataToExcel(in, "Sheet1", subClassVoList, out);

        return ResultBuildVo.success();
    }

    public void writeDataToExcel(InputStream in, String sheetName,
                                     List<SubClassVo> resultList, ServletOutputStream out) throws Exception {
        //POi读取模板
        XSSFWorkbook wb = new XSSFWorkbook(in);
        //读取sheet1中的数据
        Sheet sheet = wb.getSheet(sheetName);
        if (sheet != null) {
            //向sheet1中赋值，设置样式
            toResultListValueInfo(sheet, resultList);
        }
        //把数据写入到输出流中
        wb.write(out);
        //关闭poi方法
        wb.close();
    }

    private void toResultListValueInfo(Sheet sheet, List<SubClassVo> plantList) {
        //从第4行开始赋值
        int row_column = 3;
        int xuhao =1;
        //遍历数据集合
        for (SubClassVo obj : plantList) {
            //创建一行的方法
            Row row = sheet.createRow(row_column);
            // 给第一列序号赋值赋值
            POIClass.toCellValue(row,0, xuhao + "");
            // 给第二列编码赋值
            POIClass.toCellValue(row, 1, obj.getName() + "");
            // 给第3列名称赋值
            POIClass.toCellValue(row, 2, obj.getCode() + "");
            // 给状态赋值
            POIClass.toCellValue(row, 3, obj.getStatusName() + "");
            //给描述赋值
            POIClass.toCellValue(row, 4, obj.getRemark() + "");
            row_column++;
            xuhao++;
        }
    }

    public ResultVo validataChongFu(List<SubClassVo> subClassVoList){
        List<String> codeList = new ArrayList<>();
        List<String> nameList = new ArrayList<>();
        for (SubClassVo subClassVo:subClassVoList) {
            codeList.add(subClassVo.getCode());
            nameList.add(subClassVo.getName());
        }
        //stream
        List<String> codeAllList = new ArrayList<>();//不重复的
        List<String> repeatCodeList = new ArrayList<>();//重复的
        for (String code:codeList){
            if(codeAllList.contains(code)){
                repeatCodeList.add(code);
            }else {
                codeAllList.add(code);
            }
        }
        if (!CollectionUtils.isEmpty(repeatCodeList)){
            return ResultBuildVo.error("存在重复的编码，重复的编码是："+repeatCodeList);
        }

        return null;
    }


    public ResultVo validataRepeatIsNull(List<SubClassVo> subClassVoList){
            /*不为空字段是否为空
                * 5.长度验证
         * 7.数据转换，把汉字转换成数据库的值，状态必须填启用，禁用*/
        StringBuilder stringBuilder = new StringBuilder();
        List<String> errorMessage = new ArrayList<>();
        for (SubClassVo subClassVo:subClassVoList) {
            if (StringUtils.isEmpty(subClassVo.getName())){
//                return ResultBuildVo.error("序号"+subClassVo.getXuhao()+":"+ErrorMessage.MINGCHENGBUNENGWEIKOGN);
                stringBuilder.append("序号"+subClassVo.getXuhao()+":"+ErrorMessage.MINGCHENGBUNENGWEIKOGN);
                errorMessage.add("");
            }else {
                if (subClassVo.getName().length()>100){
//                    return ResultBuildVo.error("序号"+subClassVo.getXuhao()+":名称长度过长！");
                    stringBuilder.append(",序号"+subClassVo.getXuhao()+":"+ErrorMessage.MINGCHENGBUNENGWEIKOGN);

                }
            }
            if (StringUtils.isEmpty(subClassVo.getCode())){
                return ResultBuildVo.error("序号"+subClassVo.getXuhao()+":编码不能为空！");
            }else {
                if (subClassVo.getCode().length()>100){
                    return ResultBuildVo.error("序号"+subClassVo.getXuhao()+":编码长度过长！");
                }
            }
            if (subClassVo.getRemark().length()>300){
                return ResultBuildVo.error("序号"+subClassVo.getXuhao()+":描述长度过长！");
            }

            Integer currencyValue = StatusEnumList.getCurrencyValue(subClassVo.getStatusName());
            if (currencyValue==null){
                return ResultBuildVo.error("序号"+subClassVo.getXuhao()+":状态只能填写启用或者禁用！");
            }else {
                //三元表达式
                Boolean status = currencyValue==1?true:false;
                subClassVo.setStatus(status);
            }
        }
        if (stringBuilder.length()>0){
            return ResultBuildVo.error(stringBuilder.toString());
        }
        if (!CollectionUtils.isEmpty(errorMessage)){
            return ResultBuildVo.error(errorMessage.toString().substring(1,errorMessage.toString().length()-1));
        }

        return ResultBuildVo.success();
    }

    public static void main(String[] args) {
        String aa = "[123456]";
        String substring = aa.substring(1, aa.length()-1);
        System.out.println(substring);
    }
    public ResultVo getData(XSSFSheet sheet){
        List<SubClassVo> subClassVoList = new ArrayList<>();
        if (sheet.getLastRowNum()>3000){
            return ResultBuildVo.error("导入条数不能超过3000条，请分批次导入！");
        }
        for (int i = 3; i < sheet.getLastRowNum(); i++) {
            SubClassVo subClassVo = new SubClassVo();
            String xuhao = sheet.getRow(i).getCell(0).getStringCellValue();
            String code = sheet.getRow(i).getCell(1).getStringCellValue();
            //坑1.格式问题   坑2.读取问题 “null” null ""
            String name = sheet.getRow(i).getCell(2).getStringCellValue();
            String status = sheet.getRow(i).getCell(3).getStringCellValue();
            String remark = sheet.getRow(i).getCell(4).getStringCellValue();
            subClassVo.setCode(code);
            subClassVo.setXuhao(xuhao);
            subClassVo.setName(name);
            subClassVo.setStatusName(status);
            subClassVo.setRemark(remark);
            subClassVoList.add(subClassVo);
        }
        return ResultBuildVo.success(subClassVoList);
    }
    //验证版本号，和模板是否正确的方法
    public ResultVo validata(MultipartFile file, XSSFSheet sheet)throws Exception{
        //验证版本，最常见的，简单的方式就是判断是否包含。尾追名必须是xlsx结尾
        //string带截取字符串的功能，最后面文件的四个字符是否是xlsx
        if (!file.getOriginalFilename().contains(".xlsx")){
            return ResultBuildVo.error("文件尾缀名必须是xlsx结尾！");
        }

        XSSFCell cell = sheet.getRow(0).getCell(0);
        if (!cell.getStringCellValue().equals("备件小类导入")){
            return ResultBuildVo.error("导入模板错误");
        }
        return ResultBuildVo.success();
    }
}
